#ifndef ZHNGDI_HPP
#define ZHNGDI_HPP
#include <windows.h>
#include <gdiplus.h>
#include <iostream>
#include <string>
#include <vector>
#ifdef _MSVC_LANG
#pragma comment (lib,"Gdiplus.lib")
#endif
#define ZHNGDI_ASSERT_ERROR(e, s)       if(!(e)){std::cout<<"Zhngdi Error: "<<s<<std::endl;abort();}
#define ZHNGDI_ASSERT_WARNING(e, s)     if(!(e)){std::cout<<"Zhngdi Warning: "<<s<<std::endl;}
#define NAMESPACE_ZHNGDI_L              namespace zhngdi {
#define NAMESPACE_ZHNGDI_R              }
#define ZHNGDI_VERSION                  "1.1.7"
#ifndef Safe_Delete
#define Safe_Delete(x)                  if(x)delete x;x=nullptr
#endif
NAMESPACE_ZHNGDI_L

enum DRAW_CATEGORY { PIXEL, LINE, RECTANGLE, ELLIPSE, TEXT };
enum WINDOWS_CLOSE { NOOP, MINIMIZE, CLOSE };
enum ERROR_CODE {
    NORMAL = 1 << 0,         // No error occured.
    NONE_IMG_FILE = 1 << 1,  // Cannot find an image in specified file path.
    INDEX_OUT = 1 << 2       // Pixel index out of bounds.
};
class Figure;
typedef Figure* PFigure;
typedef Gdiplus::Bitmap* PBitmap;
typedef UINT ColorRGB;

struct POINT2D {
    int x, y;
    POINT2D(int _x = 0, int _y = 0) : x(_x), y(_y) {};
    POINT2D(const POINT2D& p) { x = p.x; y = p.y; };
    POINT2D& operator=(const POINT2D& p) { x = p.x; y = p.y; return *this; };
};

class Figure
{
public:
    Figure() {};
    ~Figure();
    // Initializes a figure with its width, height and caption name.
    Figure(int width, int height, const std::string CaptionName = "untitled");
    // Initializes a figure with a path of an image name and a caption name.
    Figure(std::string ImageName, const std::string CaptionName = "untitled");
    // Set the color of both pen and brush.
    void Set_PenColor(Gdiplus::ARGB argb);
    // Put an image from a file to a position(x, y) of the window.(Dedault position(0, 0)).
    // If you want to resize the window to fit the image size, set parameter "resize" to true.
    void Add_Image(const std::string ImageName, int x = 0, int y = 0, bool resize = true);
    ColorRGB Get_PixelColor(int x, int y);
    POINT2D Get_WindowSize();
    Gdiplus::Bitmap* Get_pBitmap();
    void Draw_Pixel(int x, int y);
    void Draw_Line(int x1, int y1, int x2, int y2);
    void Draw_Rectangle(int x1, int y1, int x2, int y2);
    void Draw_Circle(int x, int y, int r);
    void Draw_Ellipse(int x, int y, int width, int height);
    void Draw_Text(int x, int y, std::string s);
    void Close_Figure(WINDOWS_CLOSE state = WINDOWS_CLOSE::CLOSE);
    void Close_All();
    static void Window_Loop(void);
    static PFigure WindowHandle_toPFigure(HWND hWnd);
private:
    static std::vector<PFigure> _figures;
    int _id;
    UINT errCode;
    bool _closed;
    POINT2D _size;
    HWND _hWnd;
    ULONG_PTR _gdiplusToken;
    Gdiplus::Color _PenColor;
    Gdiplus::Font* _font;
    Gdiplus::Pen* _pen;
    Gdiplus::SolidBrush* _brush;
    Gdiplus::Bitmap* _bitmap;
    Gdiplus::Graphics* _graphics;
    void Initialize(int width, int height, const std::string CaptionName);
};

NAMESPACE_ZHNGDI_R
#endif
